import Algorithm from "../utils/Algorithm.js"
import Type from "../db/Type.js";
import Utils from "../utils/Utils.js";
import Db from "../db/Db.js";
import api from "../api/Api.js";
import {
    ServiceType,
    LayerType,
    staffStatusDict,
    broadcastStatusDict,
    sensorTypeDict,
    sensorStatusDict,
    sensorAlarmStatusDict
} from "../db/SafeMonitorType.js"; // 安全监控系统的 Type值
import zTreeUtils from "../utils/zTreeUtils.js";
import {colors} from "./Aci2Color.js";
import {CONF} from "../../configure/Assets.js"
import {SensorTypeU, SensorStatus} from "./SensorType.js";
import Kriging from "../utils/Kriging.js";
import Emitter from "../utils/Emitter.js";

const VectorSource = ol.source.Vector;
const VectorLayer = ol.layer.Vector;
const Feature = ol.Feature;
const Point = ol.geom.Point;
const LineString = ol.geom.LineString;
const MultiLineString = ol.geom.MultiLineString;
const Polygon = ol.geom.Polygon;
const Circle = ol.geom.Circle;
const Stroke = ol.style.Stroke;
const Text = ol.style.Text;
const Fill = ol.style.Fill;
const Style = ol.style.Style;
const CircleStyle = ol.style.Circle;
const View = ol.View;
const Overlay = ol.Overlay;
const Icon = ol.style.Icon;
const Image = ol.layer.Image;
const ImageCanvas = ol.source.ImageCanvas;
// 鹰眼地图
const OSM = ol.source.OSM
const TileLayer  = ol.layer.Tile
const Cluster = ol.source.Cluster

export default class Drawer {
    constructor() {
        if (Drawer.instance) {
            return Drawer.instance;
        }
        Drawer.instance = this;

        this.db = new Db();
        this.util = new Utils();
        this.algo = new Algorithm();
        this.config = this.algo.getConfig();
        this.kriging = new Kriging();
        this.ztreeUtils = new zTreeUtils();
        this.api = new api()
        // 触发报警时 发起报警联动
        this.emitter = new Emitter();
        // 克里金插值相关
        this.krigingParams = {
            max: 100,
            model: 'exponential',
            sigma2: 0,
            alpha: 100,
            canvasAlpha: 0.7,
            interval: 100,
            colors: [
                "#006837", "#1a9850", "#66bd63", "#a6d96a", "#d9ef8b", "#ffffbf",
                "#fee08b", "#fdae61", "#f46d43", "#d73027", "#a50026"
            ]
        }

        this.viewer = new View({
            projection: 'EPSG:3857',
            center: [0, 0],
            zoom: 8,
            enableRotation: false
        })

        this.map = new ol.Map({
            target: 'map',
            layers: [],
            view: this.viewer,
            controls: ol.control.defaults({
                zoom: false
            }),
            interactions: ol.interaction.defaults({
                doubleClickZoom: false
            })
        })

        this.drawer = {
            inserts: new VectorLayer({source: new VectorSource({wrapX: false})}),
            lwpolylines: new VectorLayer({source: new VectorSource({wrapX: false})}),
            texts: new VectorLayer({source: new VectorSource({wrapX: false})}),
            lines: new VectorLayer({source: new VectorSource({wrapX: false})}),
            mtexts: new VectorLayer({source: new VectorSource({wrapX: false})}),
            circles: new VectorLayer({source: new VectorSource({wrapX: false})}),
            arcs: new VectorLayer({source: new VectorSource({wrapX: false})}),
            splines: new VectorLayer({source: new VectorSource({wrapX: false})}),
            polylines: new VectorLayer({source: new VectorSource({wrapX: false})}),
            ellipses: new VectorLayer({source: new VectorSource({wrapX: false})}),
            hatches: new VectorLayer({source: new VectorSource({wrapX: false})}),
            tracks: new VectorLayer({source: new VectorSource({wrapX: false})}),
            positions: new VectorLayer({source: new VectorSource({wrapX: false})}),
            vehicles: new VectorLayer({source: new VectorSource({wrapX: false})}),
            persons: new VectorLayer({source: new VectorSource({wrapX: false})}),
            tunnels: new VectorLayer({source: new VectorSource({wrapX: false})}),
            tunnelpoints: new VectorLayer({source: new VectorSource({wrapX: false})}),
            faults: new VectorLayer({source: new VectorSource({wrapX: false})}),
            warnings: new VectorLayer({source: new VectorSource({wrapX: false})}),
            warningsv2: new VectorLayer({source: new VectorSource({wrapX: false})}),
            monitors: new VectorLayer({source: new VectorSource({wrapX: false})}),
            sensors: new VectorLayer({source: new VectorSource({wrapX: false})}),
            inters: new VectorLayer({source: new VectorSource({wrapX: false})}),
            waters: new VectorLayer({source: new VectorSource({wrapX: false})}),
            fissures: new VectorLayer({source: new VectorSource({wrapX: false})}),
            rootPolygon: new VectorLayer({source: new VectorSource({wrapX: false})}),
            slightPoint: new VectorLayer({source: new VectorSource({wrapX: false})}),
            modifys: new VectorLayer({source: new VectorSource({wrapX: false})}),
            measures: new VectorLayer({source: new VectorSource({wrapX: false})}),
            // 安全监控系统的新增图层
            SMStaff: new VectorLayer({source: new VectorSource({wrapX: false})}),
            SMBroadCast: new VectorLayer({source: new VectorSource({wrapX: false})}),
            SMVideo: new VectorLayer({source: new VectorSource({wrapX: false})}),
            SMVentilate: new VectorLayer({source: new VectorSource({wrapX: false}),style: this.styleFunction}),
            SMVentilateAnimation: new VectorLayer({source: new VectorSource({wrapX: false})}),
            SMGas: new VectorLayer({source: new VectorSource({wrapX: false})}),
            SMPoweredArea: new VectorLayer({source: new VectorSource({wrapX: false})}),
            // 这个地方赋值给 SMCluster的vector图层是一个临时的图层，当 真正的cluster图层被创建完成之后，他会被替换（）这里是为了防止 监听zoom事件时报错
            SMCluster: new VectorLayer({source: new VectorSource({wrapX: false})}),
            // 这是给鹰眼视图使用的缩略图层
            SmallLayer: new VectorLayer({source: new VectorSource({wrapX: false})})
        }

        this.map.addLayer(this.drawer.hatches);
        this.map.addLayer(this.drawer.warnings);
        this.map.addLayer(this.drawer.warningsv2);
        this.map.addLayer(this.drawer.lwpolylines);
        this.map.addLayer(this.drawer.lines);
        this.map.addLayer(this.drawer.circles);
        this.map.addLayer(this.drawer.arcs);
        this.map.addLayer(this.drawer.texts);
        this.map.addLayer(this.drawer.mtexts);
        this.map.addLayer(this.drawer.splines);
        this.map.addLayer(this.drawer.polylines);
        this.map.addLayer(this.drawer.ellipses);
        this.map.addLayer(this.drawer.tracks);
        this.map.addLayer(this.drawer.positions);
        this.map.addLayer(this.drawer.vehicles);
        this.map.addLayer(this.drawer.persons);
        this.map.addLayer(this.drawer.tunnels);
        this.map.addLayer(this.drawer.tunnelpoints);
        this.map.addLayer(this.drawer.faults);
        this.map.addLayer(this.drawer.monitors);
        this.map.addLayer(this.drawer.sensors);
        this.map.addLayer(this.drawer.inters);
        this.map.addLayer(this.drawer.inserts);
        this.map.addLayer(this.drawer.waters);
        this.map.addLayer(this.drawer.fissures);
        this.map.addLayer(this.drawer.rootPolygon);
        this.map.addLayer(this.drawer.slightPoint);
        this.map.addLayer(this.drawer.modifys);
        this.map.addLayer(this.drawer.measures);
        // 安全监控系统新增图层
        this.map.addLayer(this.drawer.SMStaff);
        this.map.addLayer(this.drawer.SMBroadCast);
        this.map.addLayer(this.drawer.SMVideo);
        this.map.addLayer(this.drawer.SMVentilate);
        this.map.addLayer(this.drawer.SMGas);
        this.map.addLayer(this.drawer.SMPoweredArea);
        this.map.addLayer(this.drawer.SMVentilateAnimation);


        // 地图变动后重新设置配置文件
        this.map.on('moveend', async () => {
            this.config = this.algo.getConfig();
            if (this.config === null) return;

            const oldzoom = this.config.zoom;
            const zoom = this.map.getView().getZoom();
            this.config.zoom = zoom;
            this.config.center = this.map.getView().getCenter();
            this.config.scale = Math.pow(this.config.zoom / this.config.zoomb, 2);
            this.algo.setConfig(this.config);

            // 不能放大到maxzoom的范围
            if (this.config.maxzoom !== -1 && zoom > this.config.maxzoom) {
                this.map.getView().setZoom(this.config.maxzoom);
            }

            // 不能缩小到minzoom的范围
            if (this.config.minzoom !== -1 && zoom < this.config.minzoom) {
                this.map.getView().setZoom(this.config.minzoom);
            }

            // 如果zoom小于8.5则不显示文字
            if (zoom <= 8.5) {
                this.drawer.texts.setVisible(false);
                this.drawer.mtexts.setVisible(false);
            } else {
                this.drawer.texts.setVisible(true);
                this.drawer.mtexts.setVisible(true);
            }

            // 文字需要随着比例尺放大,防止平移时闪烁
            if (Math.abs(oldzoom - zoom) > 0.5) {
                await this.draw(Type.Text);
            }
        });
    }

    init(meta, layers) {
        // 判断一下之前是否存在配置信息
        const config = this.algo.getConfig();
        let minzoom = -1, maxzoom = -1;
        if (config !== null) {
            minzoom = config.minzoom;
            maxzoom = config.maxzoom;
        }

        // 在初始化之前设置自定义样式
        this.algo.unit(meta.x, meta.y)
        this.config = {
            center: [
                this.algo.normalX(meta.x),
                this.algo.normalY(meta.y)
            ],
            istheme: this.util.getLocalStorage("theme"),
            theme: CONF.THEME,
            zoomb: 8,
            zoom: 8,
            minzoom: minzoom,
            maxzoom: maxzoom,
            scale: 1,
            meta_id: meta.meta_id,
            mine_code: meta.mine_code,
            mine_name: meta.mine_name,
            layers: layers,
            layer: []
        }

        layers.forEach(v => this.config.layer.push(v.layer));
        this.algo.setConfig(this.config);
    }

    init2() {
        // 初始化双屏
        this.map2 = new ol.Map({
            target: 'map2',
            layers: [],
            view: this.viewer,
            controls: ol.control.defaults({
                zoom: false
            }),
            interactions: ol.interaction.defaults({
                doubleClickZoom: false
            })
        })

        this.map2.addLayer(this.drawer.warnings);
        this.map2.addLayer(this.drawer.warningsv2);
        this.map2.addLayer(this.drawer.lwpolylines);
        this.map2.addLayer(this.drawer.lines);
    }

    get locked() {
        return this.lock;
    }

    set locked(lock) {
        this.lock = lock;
    }

    source(name) {
        let source
        switch (name) {
            case Type.LWPolyline:
                source = this.drawer.lwpolylines.getSource();
                break;
            case Type.Line:
                source = this.drawer.lines.getSource();
                break;
            case Type.Circle:
                source = this.drawer.circles.getSource();
                break;
            case Type.Arc:
                source = this.drawer.arcs.getSource();
                break;
            case Type.Text:
                source = this.drawer.texts.getSource();
                break;
            case Type.MText:
                source = this.drawer.mtexts.getSource();
                break;
            case Type.SPLine:
                source = this.drawer.splines.getSource();
                break;
            case Type.Polyline:
                source = this.drawer.polylines.getSource();
                break;
            case Type.Ellipse:
                source = this.drawer.ellipses.getSource();
                break;
            case Type.Hatch:
                source = this.drawer.hatches.getSource();
                break;
            case Type.Track:
                source = this.drawer.tracks.getSource();
                break;
            case Type.Position:
                source = this.drawer.positions.getSource();
                break;
            case Type.Vehicle:
                source = this.drawer.vehicles.getSource();
                break;
            case Type.Person:
                source = this.drawer.persons.getSource();
                break;
            case Type.Tunnel:
                source = this.drawer.tunnels.getSource();
                break;
            case Type.GuidePoint:
                source = this.drawer.tunnelpoints.getSource();
                break;
            case Type.Fault:
                source = this.drawer.faults.getSource();
                break;
            case Type.Warning:
                source = this.drawer.warnings.getSource();
                break;
            case Type.WarningV2:
                source = this.drawer.warningsv2.getSource();
                break;
            case Type.Monitor:
                source = this.drawer.monitors.getSource();
                break;
            case Type.Sensor:
                source = this.drawer.sensors.getSource();
                break;
            case Type.Inter:
                source = this.drawer.inters.getSource();
                break;
            case Type.Insert:
                source = this.drawer.inserts.getSource();
                break;
            case Type.Water:
                source = this.drawer.waters.getSource();
                break;
            case Type.Fissure:
                source = this.drawer.fissures.getSource();
                break;
            case Type.RootPolygon:
                source = this.drawer.rootPolygon.getSource();
                break;
            case Type.SlightPoint:
                source = this.drawer.slightPoint.getSource();
                break;
            case Type.Modify:
                source = this.drawer.modifys.getSource();
                break;
            case Type.Measure:
                source = this.drawer.measures.getSource();
                break;
            //  安全监控相关source
            case LayerType.SMStaff:
                source = this.drawer.SMStaff.getSource();
                break;
            case LayerType.SMGas:
                source = this.drawer.SMGas.getSource();
                break;
            case LayerType.SMVideo:
                source = this.drawer.SMVideo.getSource();
                break;
            case LayerType.SMBroadCast:
                source = this.drawer.SMBroadCast.getSource();
                break;
            case LayerType.SMVentilate:
                source = this.drawer.SMVentilate.getSource();
                break;
            case LayerType.SMVentilateAnimation:
                source = this.drawer.SMVentilateAnimation.getSource();
                break;
            case LayerType.SMPoweredArea:
                source = this.drawer.SMPoweredArea.getSource()
                break;
            default:
                break;
        }
        return source;
    }

    feature(type, item) {
        const feature = new Feature();
        feature.setId(item.id);
        feature.set("layer", item.layer);
        feature.set("type", type);
        feature.set("x", this.algo.normalX(item.x));
        feature.set("y", this.algo.normalY(item.y));
        feature.set("left", this.algo.normalX(item.left));
        feature.set("right", this.algo.normalX(item.right));
        feature.set("top", this.algo.normalY(item.top));
        feature.set("bottom", this.algo.normalY(item.bottom));

        let color = this._aci2color(item.color);
        let width = this._aci2width(item.width);
        if (this.config.istheme && this.config.theme !== null) {
            const theme = this.config.theme[type];
            if (theme !== undefined) {
                color = theme.color;
                width = theme.width;
            }
        }

        const stroke = new Stroke({width: width, color: color});
        feature.setStyle(new Style({stroke: stroke}));

        return feature;
    }

    addOverlay(popupId, closerId) {
        const container = document.getElementById(popupId);
        const closer = document.getElementById(closerId);
        const overlay = new Overlay({
            element: container,
            autoPan: {
                animation: {
                    duration: 250,
                }
            }
        })

        closer.onclick = function () {
            overlay.setPosition(undefined);
            closer.blur();
            return false;
        }

        this.map.addOverlay(overlay);
        return overlay;
    }

    addInteraction(obj) {
        this.map.addInteraction(obj);
    }

    removeInteraction(obj) {
        this.map.removeInteraction(obj);
    }

    getCoordinateFromPixel(pixel) {
        return this.map.getCoordinateFromPixel(pixel);
    }

    _aci2width(width) {
        return Math.ceil(0.6 * width);
    }

    _aci2color(aci) {
        return colors[aci];
    }

    _text2rotation(angle) {
        return -angle / 360 * (Math.PI * 2);
    }

    _fontSize(height) {
        let fontSize = 0;
        if (height > 40) {
            fontSize = height / 40;
        } else if (height > 30 && height <= 40) {
            fontSize = height / 35;
        } else if (height > 20 && height <= 30) {
            fontSize = height / 25;
        } else if (height > 10 && height <= 20) {
            fontSize = height / 20;
        } else if (height > 5 && height <= 10) {
            fontSize = height / 12;
        } else {
            fontSize = height / 6;
        }
        return fontSize;
    }

    async draw(name) {
        switch (name) {
            case Type.LWPolyline:
                await this._lwpolylines();
                break
            case Type.Line:
                await this._lines();
                break
            case Type.Circle:
                await this._circles();
                break
            case Type.Arc:
                await this._arcs();
                break
            case Type.Text:
                await this._texts();
                break
            case Type.MText:
                await this._mtexts();
                break
            case Type.SPLine:
                await this._splines();
                break
            case Type.Polyline:
                await this._polylines();
                break
            case Type.Ellipse:
                await this._ellipses();
                break
            case Type.Hatch:
                await this._hatches();
                break
            case Type.Track:
                await this._tracks();
                break
            case Type.Position:
                await this._positions();
                break
            case Type.GuidePoint:
                await this._tunnels();
                break
            case Type.Fault:
                await this._faults();
                break
            case Type.Warning:
                await this._warnings();
                break
            case Type.WarningV2:
                await this._warningsv2();
                break;
            case Type.Monitor:
                await this._monitors();
                break
            case Type.Inter:
                await this._inters();
                break;
            case Type.Sensor:
                await this._sensors();
                break;
            case Type.Water:
                await this._waters();
                break;
            case Type.Fissure:
                await this._fissures();
                break;
            case LayerType.SMStaff:
                await this._smstaff();
                break;
            case LayerType.SMGas:
                await this._smgas();
                break;
            case LayerType.SMVideo:
                await this._smvideo();
                break;
            case LayerType.SMBroadCast:
                await this._smbroadcast();
                break;
            case LayerType.SMVentilate:
                await this._smventilate();
                break;
            case LayerType.SMPoweredArea:
                await this._smpoweredarea();
                break;
            default:
                break
        }
    }

    async _db(name) {
        this.source(name).clear();
        return await this.db.operation(name, 'getAll');
    }

    async refresh() {
        this.config = this.algo.getConfig();
        this.inserts = new Map();
        await this._inserts();
        await this._hatches();
        await this._lwpolylines();
        await this._lines();
        await this._circles();
        await this._arcs();
        await this._texts();
        await this._mtexts();
        await this._splines();
        await this._polylines();
        await this._ellipses();
        await this._tracks();
        await this._positions();
        await this._faults();
        await this._warnings();
        await this._warningsv2();
        await this._monitors();
        await this._sensors();
        await this._waters();
        await this._fissures();
        await this._smstaff();
        // 将 refresh中的 渲染更新断电区域的函数 隐藏
        // await this._smpoweredarea();
        await this._smbroadcast();
        await this._smgas();
        // 隐藏 摄像头的渲染
        // await this._smvideo();
        await this._smventilate();
    }

    transformer(item) {
        let t = {i: false, bx: 0, by: 0, x: 0, y: 0, xs: 1, ys: 1, r: 0, show: false};
        let layerShow = false, boxShow = false, v = item;

        if (item.insert_id !== null) {
            v = this.inserts.get(item.insert_id);
            t.i = true;
            t.x = v.point[0];
            t.y = v.point[1];
            t.bx = v.base[0];
            t.by = v.base[1];
            t.xs = v.xscale;
            t.ys = v.yscale;
            t.r = v.rotation;
        }

        if (this.config.layer.includes(v.layer)) layerShow = true;
        if (this.algo.boxInBox(v.left, v.right, v.bottom, v.top)) boxShow = true;
        t.show = layerShow && boxShow;

        return t;
    }

    async _inserts(layers=[],renderAll=true) {
        const db = await this._db(Type.Insert);
        db.forEach((item) => {
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                this.inserts.set(item.insert_id, item);
            }

        })
    }

    async _lwpolylines(layers=[],renderAll=true) {
        const db = await this._db(Type.LWPolyline);
        db.forEach((item) => {
            const obj = this.transformer(item);
            if (!obj.show) return;
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                item.points.forEach((coordinate) => {
                    let d = [(coordinate[0] - obj.bx) * obj.xs, (coordinate[1] - obj.by) * obj.ys];
                    if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);
                    coordinate[0] = obj.x + d[0];
                    coordinate[1] = obj.y + d[1];
                    coordinate[0] = this.algo.normalX(coordinate[0]);
                    coordinate[1] = this.algo.normalY(coordinate[1]);
                })

                // 如果是闭合添加最后一个点
                if (item.closed) {
                    item.points.push(item.points[0]);
                }

                const feature = this.feature(Type.LWPolyline, item);
                feature.setGeometry(new LineString(item.points));
                feature.set('id',item.id)
                this.source(Type.LWPolyline).addFeature(feature);
            }
        })
    }

    async _lines(layers=[],renderAll=true) {
        const db = await this._db(Type.Line);
        db.forEach((item) => {
            const obj = this.transformer(item);
            if (!obj.show) return;
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                let d0 = [(item.start[0] - obj.bx) * obj.xs, (item.start[1] - obj.by) * obj.ys];
                if (obj.i) d0 = this.algo.twist(d0[0], d0[1], obj.r);

                item.start[0] = obj.x + d0[0];
                item.start[1] = obj.y + d0[1];

                let d1 = [(item.end[0] - obj.bx) * obj.xs, (item.end[1] - obj.by) * obj.ys];
                if (obj.i) d1 = this.algo.twist(d1[0], d1[1], obj.r);

                item.end[0] = obj.x + d1[0];
                item.end[1] = obj.y + d1[1];

                item.start[0] = this.algo.normalX(item.start[0]);
                item.start[1] = this.algo.normalY(item.start[1]);

                item.end[0] = this.algo.normalX(item.end[0]);
                item.end[1] = this.algo.normalY(item.end[1]);

                const feature = this.feature(Type.Line, item);
                feature.setGeometry(new LineString([item.start, item.end]));
                feature.set('id',item.id)
                this.source(Type.Line).addFeature(feature);
            }

        })
    }

    async _circles(layers=[],renderAll=true) {
        const db = await this._db(Type.Circle);
        db.forEach((item) => {
            const obj = this.transformer(item);
            if (!obj.show) return;
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                let d = [(item.center[0] - obj.bx) * obj.xs, (item.center[1] - obj.by) * obj.ys];
                if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                item.center[0] = obj.x + d[0];
                item.center[1] = obj.y + d[1];

                item.center[0] = this.algo.normalX(item.center[0]);
                item.center[1] = this.algo.normalY(item.center[1]);
                item.radius = this.algo.normal(item.radius);

                const feature = this.feature(Type.Circle, item)
                feature.setGeometry(new Circle(item.center, item.radius))
                feature.set('id',item.id)
                this.source(Type.Circle).addFeature(feature)
            }

        })
    }

    async _arcs(layers=[],renderAll=true) {
        const db = await this._db(Type.Arc);
        db.forEach((item) => {
            const obj = this.transformer(item);
            if (!obj.show) return;
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                let d = [(item.center[0] - obj.bx) * obj.xs, (item.center[1] - obj.by) * obj.ys];
                if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                item.center[0] = obj.x + d[0];
                item.center[1] = obj.y + d[1];

                const x = this.algo.normalX(item.center[0]);
                const y = this.algo.normalY(item.center[1]);
                const r = this.algo.normal(item.radius);
                const sa = item.start_angle
                const ea = item.end_angle

                const feature = this.feature(Type.Arc, item)
                const coordinates = this.algo.arc(x, y, r, sa, ea)
                feature.setGeometry(new LineString(coordinates))
                feature.set('id',item.id)
                this.source(Type.Arc).addFeature(feature);
            }

        })
    }

    async _texts(layers=[],renderAll=true) {
        // 这里得重新获取一下zoom信息
        this.config = this.algo.getConfig();

        const db = await this._db(Type.Text);
        db.forEach((item) => {
            const obj = this.transformer(item);
            if (!obj.show) return;
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                let d = [(item.point[0] - obj.bx) * obj.xs, (item.point[1] - obj.by) * obj.ys];
                if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                item.point[0] = obj.x + d[0];
                item.point[1] = obj.y + d[1];

                item.point[0] = this.algo.normalX(item.point[0]);
                item.point[1] = this.algo.normalY(item.point[1]);

                let rotation = this._text2rotation(item.rotation);
                if (obj.i) rotation = 0;

                const feature = this.feature(Type.Text, item);
                let fill = new Fill({color: this._aci2color(item.color)});
                if (this.config.istheme && this.config.theme !== null) {
                    const theme = this.config.theme[Type.Text];
                    if (theme !== undefined) {
                        fill = new Fill({color: theme.color});
                    }
                }

                const fontSize = this._fontSize(item.height) * this.config.scale;
                const text = new Text({
                    textAlign: "left",
                    textBaseLine: "middle",
                    rotation: rotation,
                    text: item.text,
                    fill: fill,
                    font: `normal ${fontSize}rem 微软雅黑`
                });
                feature.setStyle(new Style({text: text}));
                feature.setGeometry(new Point(item.point));
                // feature.set('id',item.id)
                this.source(Type.Text).addFeature(feature);
            }

        })
    }

    async _mtexts(layers=[],renderAll=true) {
        const db = await this._db(Type.MText)
        db.forEach((item) => {
            const obj = this.transformer(item);
            if (!obj.show) return;
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                let d = [(item.point[0] - obj.bx) * obj.xs, (item.point[1] - obj.by) * obj.ys];
                if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                item.point[0] = obj.x + d[0];
                item.point[1] = obj.y + d[1];

                item.point[0] = this.algo.normalX(item.point[0]);
                item.point[1] = this.algo.normalY(item.point[1]);

                let rotation = this._text2rotation(item.rotation);
                if (obj.i) rotation = 0;

                const feature = this.feature(Type.MText, item);
                let fill = new Fill({color: this._aci2color(item.color)});
                if (this.config.istheme && this.config.theme !== null) {
                    const theme = this.config.theme[Type.MText];
                    if (theme !== undefined) {
                        fill = new Fill({color: theme.color});
                    }
                }
                const fontSize = this._fontSize(item.height) * this.config.scale;
                const text = new Text({
                    textAlign: "center",
                    textBaseLine: "middle",
                    rotation: rotation,
                    text: item.text,
                    fill: fill,
                    font: `normal ${fontSize}rem 微软雅黑`
                });
                feature.setStyle(new Style({text: text}));
                feature.setGeometry(new Point(item.point));
                // feature.set('id',item.id)
                this.source(Type.MText).addFeature(feature);
            }

        })
    }

    async _splines(layers=[],renderAll=true) {
        const db = await this._db(Type.SPLine);
        db.forEach((item) => {
            const obj = this.transformer(item);
            if (!obj.show) return;
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                if (item.control_points !== null) {
                    item.control_points.forEach((coordinate) => {
                        let d = [(coordinate[0] - obj.bx) * obj.xs, (coordinate[1] - obj.by) * obj.ys];
                        if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                        coordinate[0] = obj.x + d[0];
                        coordinate[1] = obj.y + d[1];

                        coordinate[0] = this.algo.normalX(coordinate[0]);
                        coordinate[1] = this.algo.normalY(coordinate[1]);
                    });
                    if (item.closed) item.control_points.push(item.control_points[0]);

                    const feature = this.feature(Type.SPLine, item);
                    feature.setGeometry(new LineString(item.control_points));
                    feature.set('id',item.id)
                    this.source(Type.SPLine).addFeature(feature);
            }
            }
        })
    }

    async _polylines(layers=[],renderAll=true) {
        const db = await this._db(Type.Polyline);
        db.forEach((item) => {
            const obj = this.transformer(item);
            if (!obj.show) return;
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                item.vertices.forEach((coordinate) => {
                    let d = [(coordinate[0] - obj.bx) * obj.xs, (coordinate[1] - obj.by) * obj.ys];
                    if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                    coordinate[0] = obj.x + d[0];
                    coordinate[1] = obj.y + d[1];

                    coordinate[0] = this.algo.normalX(coordinate[0]);
                    coordinate[1] = this.algo.normalY(coordinate[1]);
                });

                // 闭合折现添加最后一个点
                if (item.is_closed) {
                    item.vertices.push(item.vertices[0]);
                }

                const feature = this.feature(Type.Polyline, item);
                feature.setGeometry(new LineString(item.vertices));
                feature.set('id',item.id)
                this.source(Type.Polyline).addFeature(feature);
            }

        })
    }

    async _ellipses(layers=[],renderAll=true) {
        const db = await this._db(Type.Ellipse);
        db.forEach((item) => {
            const obj = this.transformer(item);
            if (!obj.show) return;
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                let d = [(item.center[0] - obj.bx) * obj.xs, (item.center[1] - obj.by) * obj.ys];
                if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                item.center[0] = obj.x + d[0];
                item.center[1] = obj.y + d[1];

                const x = this.algo.normalX(item.center[0]);
                const y = this.algo.normalY(item.center[1]);
                const ux = this.algo.normal(item.major_axis[0]);
                const uy = this.algo.normal(item.major_axis[1]);
                const vx = this.algo.normal(item.minor_axis[0]);
                const vy = this.algo.normal(item.minor_axis[1]);
                const sp = item.start_param, ep = item.end_param;
                const coordinates = this.algo.ellipse(x, y, ux, uy, vx, vy, sp, ep);

                const feature = this.feature(Type.Ellipse, item);
                try {
                    // 描画椭圆个别要素还有问题，临时处理一下
                    feature.setGeometry(new LineString(coordinates));
                    feature.set('id',item.id)
                } catch (err) {
                    console.log(err, coordinates);
                    return;
                }
                this.source(Type.Ellipse).addFeature(feature);
            }

        })
    }

    async _hatches(layers=[],renderAll=true) {
        // 按照外框面积的大到小排序,目的是将面积最大的面放到最下面
        const db = await this._db(Type.Hatch);
        db.sort(((a, b) => {
            const aw = Math.abs(a.right - a.left);
            const ah = Math.abs(a.bottom - a.top);
            const bw = Math.abs(b.right - b.left);
            const bh = Math.abs(b.bottom - b.top);
            return bw * bh - aw * ah;
        }));

        db.forEach((item) => {
            const obj = this.transformer(item);
            if (!obj.show) return;
            if(renderAll || layers.some((layer) => { return layer == item.layer})) {
                const feature = this.feature(Type.Hatch, item);
                feature.set('id',item.id)
                // Hatch要特殊处理, 加上‘30’是为了让颜色透明
                const color = this._aci2color(item.color) + '30';
                const width = this._aci2width(item.width);
                let style = new Style({
                    fill: new Fill({color: color}),
                    stroke: new Stroke({color: color, width: width})
                });
                feature.setStyle(style);

                item.paths.forEach((path) => {
                    if (path.path_type === 'PolylinePath') {
                        path.polylines.forEach((polyline) => {
                            let d = [(polyline[0] - obj.bx) * obj.xs, (polyline[1] - obj.by) * obj.ys];
                            if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                            polyline[0] = obj.x + d[0];
                            polyline[1] = obj.y + d[1];

                            polyline[0] = this.algo.normalX(polyline[0]);
                            polyline[1] = this.algo.normalY(polyline[1]);
                        });
                        if (path.is_closed === 1) path.polylines.push(path.polylines[0]);
                        feature.setGeometry(new Polygon([path.polylines]));
                        this.source(Type.Hatch).addFeature(feature);
                    } else {
                        const coordinates = []
                        path.edges.forEach((edge) => {
                            // 这里将各个边组装起来
                            if (edge.edge_type === 'LineEdge') {
                                let d0 = [(edge.start[0] - obj.bx) * obj.xs, (edge.start[1] - obj.by) * obj.ys];
                                if (obj.i) d0 = this.algo.twist(d0[0], d0[1], obj.r);

                                edge.start[0] = obj.x + d0[0];
                                edge.start[1] = obj.y + d0[1];

                                let d1 = [(edge.end[0] - obj.bx) * obj.xs, (edge.end[1] - obj.by) * obj.ys];
                                if (obj.i) d1 = this.algo.twist(d1[0], d1[1], obj.r);

                                edge.end[0] = obj.x + d1[0];
                                edge.end[1] = obj.y + d1[1];

                                edge.start[0] = this.algo.normalX(edge.start[0]);
                                edge.start[1] = this.algo.normalY(edge.start[1]);
                                edge.end[0] = this.algo.normalX(edge.end[0]);
                                edge.end[1] = this.algo.normalY(edge.end[1]);

                                coordinates.push(edge.start);
                                coordinates.push(edge.end);
                            } else if (edge.edge_type === 'SplineEdge') {
                                edge.control_points.forEach(v => {
                                    let d = [(v[0] - obj.bx) * obj.xs, (v[1] - obj.by) * obj.ys];
                                    if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                                    v[0] = obj.x + d[0];
                                    v[1] = obj.y + d[1];

                                    v[0] = this.algo.normalX(v[0]);
                                    v[1] = this.algo.normalY(v[1]);
                                    coordinates.push(v);
                                });
                            } else if (edge.edge_type === 'ArcEdge') {
                                let d = [(edge.center[0] - obj.bx) * obj.xs, (edge.center[1] - obj.by) * obj.ys];
                                if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                                edge.center[0] = obj.x + d[0];
                                edge.center[1] = obj.y + d[1];

                                const x = this.algo.normalX(edge.center[0]);
                                const y = this.algo.normalY(edge.center[1]);
                                const r = this.algo.normal(edge.radius);
                                const arr = this.algo.arc(x, y, r, edge.start_angle, item.end_angle);
                                arr.forEach(v => coordinates.push(v))
                            } else if (edge.edge_type === 'EllipseEdge') {
                                let d = [(edge.center[0] - obj.bx) * obj.xs, (edge.center[1] - obj.by) * obj.ys];
                                if (obj.i) d = this.algo.twist(d[0], d[1], obj.r);

                                edge.center[0] = obj.x + d[0];
                                edge.center[1] = obj.y + d[1];

                                const x = this.algo.normalX(edge.center[0]);
                                const y = this.algo.normalY(edge.center[1]);

                                const ux = this.algo.normal(edge.major_axis[0]);
                                const uy = this.algo.normal(edge.major_axis[1]);
                                const vx = this.algo.normal(edge.minor_axis[0]);
                                const vy = this.algo.normal(edge.minor_axis[1]);
                                const arr = this.algo.ellipse(x, y, ux, uy, vx, vy, edge.start_param, edge.end_param);
                                arr.forEach(v => coordinates.push(v));
                            }
                        })

                        try {
                            // 描画Hatch个别要素还有问题，临时处理一下
                            feature.setGeometry(new Polygon([coordinates]));
                        } catch (err) {
                            console.log(err, coordinates);
                            return;
                        }
                        this.source(Type.Hatch).addFeature(feature);
                    }
                })
            }
        })
    }

    async _tracks() {
        const mode = this.util.getLocalStorage("mode");
        const edit = this.util.getLocalStorage("edit");
        const route = this.util.getLocalStorage("route");

        const db = await this._db(Type.Track);
        const blue = new CircleStyle({radius: 2, fill: new Fill({color: "#00BFFF"})});
        const orange = new CircleStyle({radius: 2, fill: new Fill({color: "orange"})});
        db.forEach((item) => {
            if (!route) {
                // 如果是非route模式,并且是编辑模型
                if (!(mode === item.type && edit)) return;
            }

            let color;
            if (item.type === "person") {
                color = "red"
            } else if (item.type === "vehicle") {
                color = "BlueViolet"
            } else {
                color = "Yellow"
            }

            for (let i = 0; i < item.points.length; i++) {
                item.points[i][0] = this.algo.normalX(item.points[i][0]);
                item.points[i][1] = this.algo.normalY(item.points[i][1]);

                // 显示开始和结束的小蓝点
                const feature = new Feature();
                if (i === 0 || i === item.points.length - 1) {
                    feature.setStyle(new Style({image: blue}));
                    feature.setGeometry(new Point(item.points[i]));
                    this.source(Type.Track).addFeature(feature);
                }

                // 如果是route模式,则不需要显示箭头
                // if (route) continue;
                //
                // if (i === 0) continue;
                //
                // const arrow = new Feature();
                // const dx = item.points[i][0] - item.points[i - 1][0];
                // const dy = item.points[i][1] - item.points[i - 1][1];
                // const rotation = Math.atan2(dy, dx);
                // const text = new Text({
                //     text: '\ue6d5',
                //     fill: new Fill({ color: color }),
                //     font: `bold 12px "iconfont"`,
                //     rotation: -rotation
                // });
                // arrow.setStyle(new Style({ text: text }));
                // const arrowX = (item.points[i][0] + item.points[i - 1][0]) / 2;
                // const arrowY = (item.points[i][1] + item.points[i - 1][1]) / 2
                // arrow.setGeometry(new Point([arrowX, arrowY]));
                // this.source(Type.Track).addFeature(arrow);
            }

            const feature = this.feature(Type.Track, item);
            const stroke = new Stroke({width: 2, color: color, lineDash: [20, 10, 40, 20]});
            feature.setId(item.id);
            feature.setStyle(new Style({stroke: stroke}));
            feature.setGeometry(new LineString(item.points));
            this.source(Type.Track).addFeature(feature);
        })
    }

    async _positions() {
        const mode = this.util.getLocalStorage("mode");
        const edit = this.util.getLocalStorage("edit");
        const route = this.util.getLocalStorage("route");
        if (mode === "vehicle" && route === "true") return;
        const src = "../../assets/images/person/station_green.png";
        const icon = new Icon({src: src});

        const db = await this._db(Type.Position);
        db.forEach((item) => {
            item.x = this.algo.normalX(item.x);
            item.y = this.algo.normalY(item.y);
            const feature = this.feature(Type.Position, item);
            feature.setId(item.id);
            feature.set("node_id", item.node_id);
            if (edit) {
                const text = new Text({
                    textAlign: "center",
                    textBaseLine: "top",
                    text: `${item.node_id}`,
                    fill: new Fill({color: 'red'}),
                    font: `bold 20px 微软雅黑`
                });
                feature.setStyle(new Style({text: text}));
                feature.setGeometry(new Point([item.x, item.y]));
                this.source(Type.Position).addFeature(feature);
            } else {
                if (mode === "vehicle") return;
                feature.setStyle(new Style({image: icon}));
                feature.setGeometry(new Point([item.x, item.y]));
                this.source(Type.Position).addFeature(feature);
            }
        })
    }

    async _tunnels() {
        const self = this;

        function guildPointS(p1, p2, width) {
            const x1 = parseFloat(p1.x), y1 = parseFloat(p1.y);
            const x2 = parseFloat(p2.x), y2 = parseFloat(p2.y);
            const k = self.algo.k(x1, y1, x2, y2);

            let lx = x1 - width * Math.sin(Math.PI - k);
            let ly = y1 - width * Math.cos(Math.PI - k);

            let rx = x1 + width * Math.sin(Math.PI - k);
            let ry = y1 + width * Math.cos(Math.PI - k);
            return [lx, ly, rx, ry];
        }

        function guildPoindE(p1, p2, width) {
            const x1 = parseFloat(p1.x), y1 = parseFloat(p1.y);
            const x2 = parseFloat(p2.x), y2 = parseFloat(p2.y);
            const k = self.algo.k(x1, y1, x2, y2)

            let lx = x2 - width * Math.sin(Math.PI - k);
            let ly = y2 - width * Math.cos(Math.PI - k);

            let rx = x2 + width * Math.sin(Math.PI - k);
            let ry = y2 + width * Math.cos(Math.PI - k);
            return [lx, ly, rx, ry];
        }

        const tunnels = await this._db(Type.Tunnel)
        this.source(Type.GuidePoint).clear();
        for (const tunnel of tunnels) {
            const width = this.algo.normal(tunnel.width) / 2;
            const gpts = await this.db.index(Type.GuidePoint, 'tunnelCode', tunnel.tunnelCode);
            gpts.sort((a, b) => {
                return b.pointIndex - a.pointIndex;
            });
            for (const item of gpts) {
                const feature = new Feature();
                feature.setId(item.id);
                feature.set('type', 'tunnels');

                const stroke = new Stroke({width: 2, color: "#ff0000"});
                feature.setStyle(new Style({stroke: stroke}));
                item.x = this.algo.normalX(item.x);
                item.y = this.algo.normalY(item.y);

                feature.setGeometry(new Circle([item.x, item.y], 0.1));
                this.source(Type.GuidePoint).addFeature(feature);
            }

            // 通过导线点生成巷道
            const lTunnelXYs = [], rTunnelXYs = [], length = gpts.length;
            if (length === 0) continue;

            // 生成除了最后一个点的左右巷道线
            for (let i = 0; i < length - 1; i++) {
                const arr = guildPointS(gpts[i], gpts[i + 1], width);
                lTunnelXYs.push([arr[0], arr[1]]);
                rTunnelXYs.push([arr[2], arr[3]]);
            }

            // 计算最后一个点生成的巷道点
            if (length >= 2) {
                const arr = guildPoindE(gpts[length - 2], gpts[length - 1], width);
                lTunnelXYs.push([arr[0], arr[1]]);
                rTunnelXYs.push([arr[2], arr[3]]);
            }

            const tunnelFeature = new Feature();
            const stroke = new Stroke({width: 3, color: "#00ff00"});
            tunnelFeature.setStyle(new Style({stroke: stroke}));
            tunnelFeature.setId(tunnel.tunnelCode);
            tunnelFeature.set("type", Type.Tunnel);
            tunnelFeature.set("mineCode", tunnel.mineCode);
            tunnelFeature.set("tunnelCode", tunnel.tunnelCode);

            tunnelFeature.setGeometry(new MultiLineString([lTunnelXYs, rTunnelXYs]));
            this.source(Type.Tunnel).addFeature(tunnelFeature);
        }
    }

    async _faults() {
        const db = await this._db(Type.Fault)
        for (const fault of db) {
            const start = fault.startPoint.split(',');
            const end = fault.endPoint.split(',');
            const drop = fault.directionPoint.split(',');

            // 正则化坐标
            start[0] = this.algo.normalX(parseFloat(start[0]));
            start[1] = this.algo.normalY(parseFloat(start[1]));
            end[0] = this.algo.normalX(parseFloat(end[0]));
            end[1] = this.algo.normalY(parseFloat(end[1]));
            drop[0] = this.algo.normalX(parseFloat(drop[0]));
            drop[1] = this.algo.normalY(parseFloat(drop[1]));

            // 计算断层指向线的长度
            const width = this.algo.distance(start[0], start[1], end[0], end[1]) / 10;

            // 计算中心点、斜率、 描画横线
            const cx = (start[0] + end[0]) / 2, cy = (start[1] + end[1]) / 2;
            const scx = (start[0] + cx) / 2, scy = (start[1] + cy) / 2;
            const ecx = (end[0] + cx) / 2, ecy = (end[1] + cy) / 2;
            const k = this.algo.k(cx, cy, drop[0], drop[1]), l = [start, end];
            const left = this.algo.pointIsLineLR(drop, start, end);
            const d = left ? k + Math.PI : k;

            // 描画中间竖线
            const cdx = cx + width * Math.cos(d), cdy = cy + width * Math.sin(d);
            const cdl = [[cx, cy], [cdx, cdy]];

            // 描画左端竖线
            const scdx = scx + width / 2 * Math.cos(d), scdy = scy + width / 2 * Math.sin(d);
            const scdl = [[scx, scy], [scdx, scdy]];

            // 描画右端竖线
            const ecdx = ecx + width / 2 * Math.cos(d), ecdy = ecy + width / 2 * Math.sin(d);
            const ecdl = [[ecx, ecy], [ecdx, ecdy]];

            // 描画三角
            const w1 = d + Math.PI * 7 / 6, w2 = d + Math.PI * 5 / 6;
            const asx = cdx + width / 2 * Math.cos(w1), asy = cdy + width / 2 * Math.sin(w1);
            const esx = cdx + width / 2 * Math.cos(w2), esy = cdy + width / 2 * Math.sin(w2);
            const al = [[asx, asy], [cdx, cdy], [esx, esy]];

            // 将所有的线段组织成多线
            const stroke = new Stroke({width: 1, color: "#ff0000"});
            const style = new Style({stroke: stroke});
            const multiLineStringFeature = new Feature();
            multiLineStringFeature.setId(fault.id);
            multiLineStringFeature.set("faultCode", fault.faultCode);
            multiLineStringFeature.set('type', Type.Fault);
            multiLineStringFeature.setStyle(style);
            multiLineStringFeature.setGeometry(new MultiLineString([l, cdl, scdl, ecdl, al]));
            this.source(Type.Fault).addFeature(multiLineStringFeature);
        }
    }

    async _monitors() {
        const db = await this._db(Type.Monitor);
        db.forEach((item) => {
            const x = this.algo.normalX(item.point[0]);
            const y = this.algo.normalY(item.point[1]);
            const feature = new Feature();
            feature.setId(item.id);
            feature.set("type", Type.Monitor);
            const text = new Text({
                text: '\ue702',
                fill: new Fill({color: "pink"}),
                font: `normal 25px "iconfont"`
            });
            feature.setStyle(new Style({text: text}));
            feature.setGeometry(new Point([x, y]));
            this.source(Type.Monitor).addFeature(feature);
        });
    }

    async _warnings() {
        const db = await this._db(Type.Warning);
        db.forEach(item => {
            if (item.geoJson === null) return;

            const feature = new Feature();
            feature.setId(item.warnAreaCode);
            feature.set('type', Type.Warning);
            feature.set("version", "v1");
            feature.set("warningDateTime", item.warningDateTime);
            feature.set("warningPosition", item.warningPosition);
            feature.set("warningType", item.warningType);
            feature.set("warningLevel", item.warningLevel);
            feature.set("hazardReason", item.hazardReason);
            feature.set("hazardSuggest", item.hazardSuggest);
            feature.set("warningCancelTime", item.warningCancelDateTime);

            const style = new Style({
                fill: new Fill({color: '#FF000066'}),
                stroke: new Stroke({color: '#FF000066', width: 1})
            })
            feature.setStyle(style);

            const json = JSON.parse(item.geoJson);
            const type = json.geometry.type;
            const subType = json.properties.subType;
            const coordinates = json.geometry.coordinates;
            if (coordinates === null || coordinates === undefined) {
                return;
            }

            if (type === "Point") {
                coordinates[0] = this.algo.normalX(coordinates[0]);
                coordinates[1] = this.algo.normalY(coordinates[1]);
                if (subType === "Point") {
                    feature.setGeometry(new Circle(coordinates, this.algo.normal(10)));
                } else if (subType === "Circle") {
                    const radius = json.properties;
                    feature.setGeometry(new Circle(coordinates, this.algo.normal(radius)));
                } else if (subType === "Ellipse") {
                    const cx = coordinates[0];
                    const cy = coordinates[1];
                    const ux = json.properties.semiMajorAxis, uy = 0;
                    const vx = 0, vy = json.properties.semiMinorAxis;
                    this.algo.ellipse(cx, cy, ux, uy, vx, vy);
                }
            } else if (type === "Polygon" && subType === "Polygon") {
                for (const coor of coordinates) {
                    coor[0] = this.algo.normalX(coor[0]);
                    coor[1] = this.algo.normalY(coor[1]);
                }
                feature.setGeometry(new Polygon([coordinates]));
            }
            this.source(Type.Warning).addFeature(feature);
        });
    }

    async _warningsv2() {
        const db = await this._db(Type.WarningV2);

        // 因为预警面包含报警面,所以这里先画
        db.forEach((item) => {
            if (item.type !== "warning") return;

            item.points.forEach((point) => {
                point[0] = this.algo.normalX(point[0]);
                point[1] = this.algo.normalY(point[1]);
            });

            const feature = new Feature();
            feature.setId(item.id);
            feature.set("type", Type.WarningV2);
            feature.set("dxftype", item.type);
            feature.set("version", "v2");
            feature.setStyle(new Style({fill: new Fill({color: '#FFF80066'})}));
            feature.setGeometry(new Polygon([item.points]));
            this.source(Type.WarningV2).addFeature(feature);
        });

        db.forEach((item) => {
            if (item.type !== "alarm") return;

            item.points.forEach((point) => {
                point[0] = this.algo.normalX(point[0]);
                point[1] = this.algo.normalY(point[1]);
            });

            const feature = new Feature();
            feature.setId(item.id);
            feature.set("type", Type.WarningV2);
            feature.set("dxftype", item.type);
            feature.set("version", "v2");
            feature.setStyle(new Style({fill: new Fill({color: '#DC143C66'})}));
            feature.setGeometry(new Polygon([item.points]));
            this.source(Type.WarningV2).addFeature(feature);
        });
    }

    async _sensors() {
        const db = await this._db(Type.Sensor);
        db.forEach((item) => {
            if (item.x === 0 && item.y === 0 && item.z === 0) {
                return;
            }

            const x = this.algo.normalX(item.x);
            const y = this.algo.normalY(item.y);
            const feature = new Feature();
            feature.setId(item.id);
            feature.set('type', Type.Sensor);
            feature.set('disasterType', item.disasterType);
            feature.set('sensorType', item.sensorType);
            feature.set('sensorTypeName', item.sensorTypeName);
            feature.set('parentNodeId', item.parentNode.id);
            feature.set('label', item.label);
            feature.set('x', x);
            feature.set('y', y);
            const text = new Text({
                text: SensorTypeU[item.sensorType],
                fill: new Fill({color: SensorStatus[item.sensorStatus]}),
                font: `normal 20px "iconfont"`
            });
            feature.setStyle(new Style({text: text}));
            feature.setGeometry(new Point([x, y]));
            this.source(Type.Sensor).addFeature(feature);
        })
    }

    async _waters() {
        const db = await this._db(Type.Water);
        db.forEach((item) => {
            if (item.geoJson === null) return;

            const feature = new Feature();
            feature.setId(item.id);
            feature.set('type', Type.Water);

            const json = JSON.parse(item.geoJson);
            const coordinates = json.geometry.coordinates;

            const style = new Style({
                fill: new Fill({color: '#0000FF33'}),
                stroke: new Stroke({color: '#0000FF33', width: 1})
            })
            feature.setStyle(style);

            for (const coor of coordinates) {
                coor[0] = this.algo.normalX(coor[0]);
                coor[1] = this.algo.normalY(coor[1]);
            }
            feature.setGeometry(new Polygon([coordinates]));
            this.source(Type.Water).addFeature(feature);
        });
    }

    async _fissures() {
        const db = await this._db(Type.Fissure);
        db.forEach((item) => {
            if (item.geoJson === null) return;

            const feature = new Feature();
            feature.setId(item.id);
            feature.set('type', Type.Fissure);

            const json = JSON.parse(item.geoJson);
            const coordinates = json.geometry.coordinates;

            const style = new Style({
                fill: new Fill({color: '#00FFFF'}),
                stroke: new Stroke({color: '#00FFFF', width: 1})
            })
            feature.setStyle(style);

            for (const coor of coordinates) {
                coor[0] = this.algo.normalX(coor[0]);
                coor[1] = this.algo.normalY(coor[1]);
            }

            feature.setGeometry(new LineString(coordinates));
            this.source(Type.Fissure).addFeature(feature);
        });
    }

    _inters() {
        const config = this.algo.getConfig();
        if (config === null) return;

        const model = this.krigingParams.model;
        const sigma2 = this.krigingParams.sigma2;
        const alpha = this.krigingParams.alpha;
        const interval = this.krigingParams.interval;
        const colors = this.krigingParams.colors;

        const kriging = this.util.getLocalStorage("kriging");
        if (kriging === null) return;

        for (let i = 0; i < kriging.lngs.length; i++) {
            kriging.lngs[i] = this.algo.normalX(kriging.lngs[i]);
        }

        for (let i = 0; i < kriging.lats.length; i++) {
            kriging.lats[i] = this.algo.normalY(kriging.lats[i]);
        }

        kriging.polygons[0].forEach(item => {
            item[0] = this.algo.normalX(item[0]);
            item[1] = this.algo.normalY(item[1]);
        })

        kriging.width = this.algo.normal(kriging.width);

        const variogram = this.kriging.train(kriging.values, kriging.lngs, kriging.lats, model, sigma2, alpha);
        const grid = this.kriging.grid(kriging.polygons, variogram, interval);

        if (this.drawer.inters !== null) {
            this.map.removeLayer(this.drawer.inters);
        }

        this.drawer.inters = new Image({
            source: new ImageCanvas({
                canvasFunction: (extent, resolution, pixelRatio, size, projection) => {
                    let canvas = document.createElement('canvas');
                    canvas.width = size[0];
                    canvas.height = size[1];
                    canvas.style.display = 'bck';

                    // 设置canvas透明度
                    canvas.getContext('2d').globalAlpha = this.canvasAlpha;

                    // 使用分层设色渲染
                    this.kriging.plot(canvas, grid, [extent[0], extent[2]], [extent[1], extent[3]], colors);
                    return canvas;
                },
                projection: 'EPSG:3857'
            })
        })

        //向map添加图层
        this.map.addLayer(this.drawer.inters);
    }

    // 安全监控相关的refresh 对应图层的方法
    async _smstaff() {
        // 获取indexDb中的相关数据
        const staffDb = await this._db(LayerType.SMStaff)
        const staffSource = this.source(LayerType.SMStaff)
        staffSource.clear()
        // 获取 数据库里面的 人员分站数据
        const {data: staffinfo} = await this.ztreeUtils.getSelectedStaffNodes()
        staffinfo.forEach((info) => {
            const res = staffDb.find((dbinfo) => {
                return info.node_id == dbinfo.node_id
            })
            info.x = res.x, info.y = res.y, info.status = staffStatusDict[info.status]
            const src = `assets/images/safe_monitor/staff/reader_${info.status}.png`
            const style = new Style(
                {
                    image: new Icon({
                        src: src
                    }),
                    text: new Text({
                        font: '8px Microsoft YaHei',
                        text: `${info.node_id}-${info.placement}-读卡器`,
                        fill: new ol.style.Fill({
                            color: '#666'
                        }),
                        offsetY: 18
                    })
                }
            )
            const staffFeature = new Feature()
            staffFeature.set('type', LayerType.SMStaff)
            staffFeature.set('service_type', ServiceType.Staff)
            staffFeature.set('node_id', info.node_id)
            staffFeature.set('show_text', `${info.node_id}-${info.placement}-读卡器`)
            staffFeature.setStyle(style)
            const x = this.algo.normalX(info.x),y = this.algo.normalY(info.y)
            staffFeature.setGeometry(new Point([x, y]));
            staffSource.addFeature(staffFeature)
        })
    }

    async _smgas() {
        // 预览模式下，才去清空通风设备的 风向的overlay
        if(!this.util.getLocalStorage('edit')) {
            // 获取 传感器的关联数据并传给报警管理组件
            const {data:links} = await this.ztreeUtils.getGasintegration()
            this.emitter.emit('integration-receive',links)
            // 获取 断电区域数据并传给报警管理组件
            // const {data:areadata} = await this.api.getSmPoweredAreas()
            // this.emitter.emit('powered-areas-receive',areadata.areasInfo)
        }
        // 获取 view_gas_data的传感器数据（所有已经被设置过位置的监控分站与传感器）
        const gasData = await this.ztreeUtils.getSelectedGasNodes()
        const {data} = gasData
        data.forEach((el) => {
            // 根据node_id 确定传感器类型
            const node_id = el.node_id
            if (node_id.length != 3) {
                el.type = '传感器'
                el.station_Id = node_id.slice(0, 3) // 截取获取传感器 所属的监控分站的id
                el.channel_Id = node_id.slice(3, 5) // 截取获取传感器 在对应监控分站上的通道号
                el.channel_Code = node_id.slice(5, 7) // 截取获取传感器 在对应分站上的对应通道上的编号
                el.sensor_Type = node_id.slice(7, 8) // 值只有三个 A,D,E  分别代表: A - 模拟量, D - 数字量， E - 电源
            } else {
                el.type = '分站'
                el.station_Id = null
                el.channel_Id = null
                el.channel_Code = null
                el.sensor_Type = null
            }
        })
        const gasSource = this.source(LayerType.SMGas)
        gasSource.clear()
        data.forEach((el) => {
            const {typename, basepath, imgname} = sensorTypeDict[el.node_type] ?? sensorTypeDict['default']
            const gasStatus = sensorStatusDict[el.status]
            const src = basepath + gasStatus + imgname
            const alarmStatus = sensorAlarmStatusDict[el.alarm]
            const style = new Style({
                image: new Icon({
                    src: src
                }),
                text: new Text({
                    font: '8px Microsoft YaHei',
                    text: `${el.node_id}-${el.node_type}-${el.real_data == null ? '分站' : el.real_data }`,
                    fill: new ol.style.Fill({
                        color: '#646464'
                    }),
                    offsetY: 18
                })
            })
            const gasfeature = new Feature()
            gasfeature.set('type', LayerType.SMGas)
            gasfeature.set('service_type', ServiceType.Gas)
            gasfeature.set('node_id', el.node_id)
            gasfeature.set('parent_id', el.parent_id)
            gasfeature.set('station_Id', el.station_Id)
            gasfeature.set('channel_Id', el.channel_Id)
            gasfeature.set('channel_Code', parseInt(el.channel_Code))
            gasfeature.set('sensor_Type', el.sensor_Type)
            gasfeature.set('show_text',`${el.node_id}-${el.node_type}-${el.type}`)
            gasfeature.setStyle(style)
            const x = this.algo.normalX(el.x),y = this.algo.normalY(el.y)
            gasfeature.setGeometry(new Point([x, y]));
            // 当map中的元素处于聚合状态下，不触发报警
            const clusterVisibleStatus = this.drawer.SMCluster.getVisible()
            if(alarmStatus && el.type == '传感器' && !this.util.getLocalStorage('edit') && !clusterVisibleStatus) {
                const denormalX = this.algo.denormalX(x),denormalY = this.algo.denormalY(y)
                this.ztreeUtils.highLightAnimation([denormalX, denormalY],3000,'alarm')
                // 传感器报警 触发联动报警
                this.emitter.emit("sm-alarm-relation",el.node_id)
            }
            gasSource.addFeature(gasfeature)
        })
    }

    async _smvideo() {
        // 获取indexDb中的相关数据
        const videoDb = await this._db(LayerType.SMVideo)
        // 获取kj83上的videoinfo数据
        const {data:videoinfo} = await this.ztreeUtils.getSelectedVideoNodes()
        const mergeInfoVideos = []
        videoDb.forEach((vdb) => {
            videoinfo.forEach((vinfo) => {
                if(vdb.node_id == vinfo.node_id) {
                    const mergeVideo = Object.assign(vdb,vinfo)
                    mergeInfoVideos.push(mergeVideo)
                }
            })
        })
        const videoSource = this.source(LayerType.SMVideo)
        videoSource.clear()
        const src = `assets/images/safe_monitor/video/video_normal.png`
        mergeInfoVideos.forEach((video) => {
            const style = new Style(
                {
                    image: new Icon({
                        src: src
                    }),
                    text: new Text({
                        font: '8px Microsoft YaHei',
                        text: `${video.place}-${video.device_id}-${video.manufacture}`,
                        fill: new ol.style.Fill({
                            color: '#666'
                        }),
                        offsetY: 18
                    })
                }
            )
            const videoFeature = new Feature()
            videoFeature.set('service_type', ServiceType.Video)
            videoFeature.set('node_id', video.node_id)
            videoFeature.set('type', LayerType.SMVideo)
            videoFeature.set('show_text',`${video.place}-${video.device_id}-${video.manufacture}`)
            videoFeature.setStyle(style)
            const x = this.algo.normalX(video.x),y = this.algo.normalY(video.y)
            videoFeature.setGeometry(new Point([x, y]));
            videoSource.addFeature(videoFeature)
        })
    }
    // 重新更新断电区域图层
    async _smpoweredarea() {
        const area_source = this.source(LayerType.SMPoweredArea)
        area_source.clear()
        // 获取 放在 kj83 上的断点区域的信息（包括 id，name，与传感器关联关系）
        const {data:AreaData} = await this.api.getSmPoweredAreas()
        const {areasInfo,areasPosition} = AreaData
        // 对数据进行整合
        const formatAreaList = areasInfo.map((el) => {
            const item = areasPosition.find((a) => {
                return a.id == el.id
            })
            el.points = JSON.parse(item.points)
            if(el.name == 'null') {
                el.name = ''
            }
            return el
        })
        formatAreaList.forEach((info) => {
            const style = new ol.style.Style({
                fill: new ol.style.Fill({
                    color: 'rgba(255, 255, 255, 0.3)'
                }),
                stroke: new ol.style.Stroke({
                    color: '#5698da',
                    width: 2
                }),
                text: new ol.style.Text({
                    text:info.name,
                    fill: new ol.style.Fill({
                        color: 'white'
                    }),
                })
            })
            const PoweredAreaFeature = new Feature()
            PoweredAreaFeature.set('service_type', ServiceType.PoweredArea)
            PoweredAreaFeature.set('type', LayerType.SMPoweredArea)
            PoweredAreaFeature.set('id', info.id)
            PoweredAreaFeature.setStyle(style)
            const normalPoints = info.points.map((point) => {
                return [this.algo.normalX(point[0]),this.algo.normalY(point[1])]
            })
            PoweredAreaFeature.setGeometry(new Polygon([normalPoints]));
            area_source.addFeature(PoweredAreaFeature)
            console.log('完成断电区域元素的渲染')
        })
    }

    async _smbroadcast() {
        // 获取indexDb中的相关数据
        const broadcastDb = await this._db(LayerType.SMBroadCast)
        // 获取 数据库里面的 人员分站数据
        const {data: broadinfo} = await this.ztreeUtils.getSelectedBroadCastNodes()
        const broadcastSource = this.source(LayerType.SMBroadCast)
        broadcastSource.clear()
        broadinfo.forEach((info) => {
            const res = broadcastDb.find((dbinfo) => {
                return info.node_id == dbinfo.node_id
            })
            info.x = res.x, info.y = res.y, info.status = broadcastStatusDict[info.status]
            const src = `assets/images/safe_monitor/broadcast/broadcast_${info.status}.png`
            const style = new Style(
                {
                    image: new Icon({
                        src: src
                    }),
                    text: new Text({
                        font: '8px Microsoft YaHei',
                        text: `${info.node_id}-${info.place}-广播终端`,
                        fill: new ol.style.Fill({
                            color: '#666'
                        }),
                        offsetY: 18
                    })
                }
            )
            const broadcastFeature = new Feature()
            broadcastFeature.set('type', LayerType.SMBroadCast)
            broadcastFeature.set('service_type', ServiceType.BroadCast)
            broadcastFeature.set('node_id', info.node_id)
            broadcastFeature.set('node_type', info.node_type)
            broadcastFeature.set('place', info.place)
            broadcastFeature.set('status', info.status)
            broadcastFeature.set('alarm', info.alarm)
            broadcastFeature.set('show_text',`${info.node_id}-${info.place}-${info.node_type}`)
            broadcastFeature.setStyle(style)
            // 使用算法 转换 x,y的值
            const x = this.algo.normalX(info.x),y = this.algo.normalY(info.y)
            // console.log('info x- info y',info.x,info.y)
            // console.log('xxxxx-yyyyy',x,y)
            broadcastFeature.setGeometry(new Point([x, y]));
            broadcastSource.addFeature(broadcastFeature)
        })
    }

    async _smventilate() {
        // 获取indexDb中的相关数据
        const ventilateDb = await this._db(LayerType.SMVentilate)
        const ventilateSource = this.source(LayerType.SMVentilate)
        ventilateSource.clear()
        const ventilateAnimationSource = this.source(LayerType.SMVentilateAnimation)
        ventilateAnimationSource.clear()
        this.emitter.emit('ventilate-animation-clear')
        ventilateDb.forEach((ventilate) => {
            // 每个ventilate的 坐标进行转换
            ventilate.start_x = this.algo.normalX(ventilate.start_x)
            ventilate.start_y = this.algo.normalY(ventilate.start_y)
            ventilate.end_x = this.algo.normalX(ventilate.end_x)
            ventilate.end_y = this.algo.normalY(ventilate.end_y)
            const feature = new Feature()
            feature.set('id',ventilate.id)
            feature.set('ventilateType',ventilate.ventilateType)
            feature.set('type',LayerType.SMVentilate)
            feature.setGeometry(new LineString([[ventilate.start_x,ventilate.start_y],[ventilate.end_x,ventilate.end_y]]))
            ventilateSource.addFeature(feature)
            // 为了让通风路径具备动画效果，我们把每个通风路径交给专门负责这个功能的组件处理
            this.emitter.emit('ventilate-animation',ventilate)
        })

    }

    fotKrigingLayer(data) {
        const {model, sigma2, alpha, interval} = this.krigingParams
        const {
            data: oData,
            map = 'map',
            params: {
                colors,
                krigingModel = model,
                krigingSigma2 = sigma2,
                krigingAlpha = alpha,
                canvasAlpha = 1,
                krigingInterval = interval
            }
        } = data;

        if (oData.length < 3) {
            alert('样点数据不足');
            return;
        }

        const tempMap = map === 'map2' ? this.map2 : this.map;
        let minX, maxX, minY, maxY;
        let values = []
        let lngs = []
        let lats = []

        oData.forEach(({x, y, energy}, index) => {
            const lng = this.algo.normalX(x);
            const lat = this.algo.normalY(y);
            if (index === 0) {
                minX = maxX = lng;
                minY = maxY = lat;
            } else {
                minX = minX > lng ? lng : minX
                maxX = maxX > lng ? maxX : lng
                minY = minY > lat ? lat : minY
                maxY = maxY > lat ? maxY : lat
            }
            lngs.push(lng)
            lats.push(lat)
            values.push(energy)
        })

        const polygons = [[[minX, minY], [maxX, minY], [maxX, maxY], [minX, maxY], [minX, minY]]];
        const variogram = this.kriging.train(values, lngs, lats, krigingModel, krigingSigma2, krigingAlpha);
        const grid = this.kriging.grid(polygons, variogram, (maxX - minX) / krigingInterval);

        if (this.drawer.inters !== null) {
            tempMap.removeLayer(this.drawer.inters);
        }

        this.drawer.inters = new Image({
            source: new ImageCanvas({
                canvasFunction: (extent, resolution, pixelRatio, size, projection) => {
                    let canvas = document.createElement('canvas');
                    canvas.width = size[0];
                    canvas.height = size[1];
                    canvas.style.display = 'block';

                    // 设置canvas透明度
                    canvas.getContext('2d').globalAlpha = canvasAlpha;

                    // 使用分层设色渲染
                    this.kriging.plot(canvas, grid, [extent[0], extent[2]], [extent[1], extent[3]], colors);
                    return canvas;
                },
                projection: 'EPSG:3857'
            })
        })

        const polygonRect = turf.polygon(polygons);
        const centroid = turf.centroid(polygonRect);
        this.map.getView().animate({ // 只设置需要的属性即可
            center: centroid.geometry.coordinates, // 中心点
            duration: 1000, // 缩放持续时间，
            zoom: 3
        })
        //向map添加图层
        tempMap.addLayer(this.drawer.inters);
    }

    async location() {
        this.config = this.algo.getConfig();
        if (this.config !== null) {
            this.map.getView().setCenter(this.config.center);
            this.map.getView().setZoom(this.config.zoom);
        }
        await this.refresh();
        this.refreshLayerCustomColor()
    }

    async _smRefreshMetaByLayers(layersArr) {
        this._lines(layersArr,false)
        this._lwpolylines(layersArr,false)
        this._circles(layersArr,false)
        this._arcs(layersArr,false)
        this._texts(layersArr,false)
        this._mtexts(layersArr,false)
        this._splines(layersArr,false)
        this._polylines(layersArr,false)
        this._ellipses(layersArr,false)
        this._hatches(layersArr,false)
    }
    createControl() {
        // 初始化鹰眼视图
        const linelayer = this.source(Type.Line)
        const lwpolylinelayer = this.source(Type.LWPolyline)
        const polylinelayer = this.source(Type.Polyline)
        const lineFeatures = linelayer.getFeatures()
        const lwpolylineFeatures = lwpolylinelayer.getFeatures()
        const polylineFeatures = polylinelayer.getFeatures()
        const mergeFeatures = [...lineFeatures,...lwpolylineFeatures,...polylineFeatures]
        const smallLayer = this.drawer.SmallLayer
        const smallLayerSource = smallLayer.getSource()
        for(let i = 0;i < mergeFeatures.length;i++) {
            smallLayerSource.addFeature(mergeFeatures[i])
        }
        const overviewMapControl = new ol.control.OverviewMap({
            className: 'ol-overviewmap custom-overviewmap',
            layers: [
                smallLayer
            ],
            tipLabel: '鹰眼地图'
        });
        this.map.addControl(overviewMapControl)
        // 初始化重置视图
        const ZoomControl = new ol.control.ZoomToExtent({
            className: 'custom-zoom-extent',
            extent: linelayer.bounds,
            label: (function () {
                // 使用 Font-Awesome 的字符
                let span = document.createElement('span');
                span.className = 'fa fa-sync';
                return span;
            })(),
            tipLabel: '重置视图'
        })
        this.map.addControl(ZoomControl)
        // 初始化 cluster图层
        this.initCluster()
    }
//    用于绘制风向线段的函数
    styleFunction(feature) {
        const geometry = feature.getGeometry();
        const ventilateType = feature.get('ventilateType')
        const styles = [
            // linestring
            new Style({
                stroke: new Stroke({
                    color: '#ffcc33',
                    width: 2,
                }),
            }),
        ];
        let src = 'assets/images/safe_monitor/ventilate/icon-arrow-jinfeng.png'
        if(ventilateType == '进风') {
            src = 'assets/images/safe_monitor/ventilate/icon-arrow-jinfeng.png'
        }
        else {
            src = 'assets/images/safe_monitor/ventilate/icon-arrow-huifeng.png'
        }
        const length = geometry.getLength()
        const step = Math.floor(length / 8000)
        const coordinates = geometry.getCoordinates()
        const start = coordinates[0],end = coordinates[1]
        const step_y_len = Math.floor((end[1] - start[1]) / step),step_x_len = Math.floor((end[0] - start[0]) / step)
        const rotation = Math.atan2(end[1]-start[1], end[0]-start[0]);
        for(let i = 1;i <= step;i++) {
            const point = [start[0] + i * step_x_len,start[1] + i * step_y_len]
            styles.push(
                new Style({
                    geometry: new Point(point),
                    image: new Icon({
                        src: src,
                        scale:0.5,
                        anchor: [0.75, 0.5],
                        rotateWithView: true,
                        rotation: -rotation,
                    }),
                })
            );
        }
        return styles;
    }
    // 初始化 cluster
    initCluster() {
        // 初始化 元素集群功能
        const gasFeatures = this.source(LayerType.SMGas).getFeatures()
        const staffFeatures = this.source(LayerType.SMStaff).getFeatures()
        const broadcastFeatures = this.source(LayerType.SMBroadCast).getFeatures()
        const source = new VectorSource({
            features: [...gasFeatures,...staffFeatures,...broadcastFeatures],
        });
        const clusterSource = new Cluster({
            distance: 150,
            minDistance: 100,
            source: source,
        });
        // 生成聚合图层
        const styleCache = {};
        const clusters = new VectorLayer({
            source: clusterSource,
            style: function (feature) {
                const size = feature.get('features').length;
                let style = styleCache[size];
                if (!style) {
                    const style = new Style({
                        image: new CircleStyle({
                            radius: 10,
                            stroke: new Stroke({
                                color: '#fff',
                            }),
                            fill: new Fill({
                                color: '#3399CC',
                            }),
                        }),
                        text: new Text({
                            text: size.toString(),
                            fill: new Fill({
                                color: '#fff',
                            }),
                        }),
                    });
                    styleCache[size] = style;
                }
                return style;
            },
        });
        // 将生成的 cluster图层存储起来
        this.map.removeLayer(this.drawer.SMCluster)
        this.drawer.SMCluster = clusters
        // 初始化创建 cluster的时候应该先直接隐藏他
        this.map.addLayer(this.drawer.SMCluster)
        // 判断传感器图层
        const gasLayerIsShow = this.drawer.SMGas.getVisible()
        if(gasLayerIsShow) {
            this.drawer.SMCluster.setVisible(false)
        }
        else {
            this.drawer.SMCluster.setVisible(true)
        }

    }
    // 根据自定义的图纸图层的颜色，重新渲染相关图层的颜色
    async refreshLayerCustomColor() {
        const layerInfos = await this.db.operation('layer','getAll')
        const lineFeatures = this.drawer.lines.getSource().getFeatures()
        const hatchFeatures = this.drawer.hatches.getSource().getFeatures()
        const lwPolyLineFeatures = this.drawer.lwpolylines.getSource().getFeatures()
        const arcsFeatures = this.drawer.arcs.getSource().getFeatures()
        const circleFeatures = this.drawer.circles.getSource().getFeatures()
        const ellipseFeatures = this.drawer.ellipses.getSource().getFeatures()

        const mergeFeatures = [...arcsFeatures,...ellipseFeatures,...circleFeatures,...lineFeatures,...hatchFeatures,...lwPolyLineFeatures]
        mergeFeatures.forEach((line) => {
            const layername = line.get('layer')
            const info = layerInfos.find((info) => {
                return info.layer == layername
            })
            // 设置了 自定义颜色的话
            if(info.customColor) {
                const style = line.getStyle()
                const stroke = style.getStroke()
                stroke.setColor(info.customColor)
                style.setStroke(stroke)
                line.setStyle(style)
            }
        })
    }

    // 对鹰眼视图的 缩略图层进行 更新（当图纸发生更新时，这个需要执行一下）
    refreshSmallLayer() {
        const sLayer = this.drawer.SmallLayer
        sLayer.getSource().clear()
        const linelayer = this.source(Type.Line)
        const lwpolylinelayer = this.source(Type.LWPolyline)
        const polylinelayer = this.source(Type.Polyline)
        const lineFeatures = linelayer.getFeatures()
        const lwpolylineFeatures = lwpolylinelayer.getFeatures()
        const polylineFeatures = polylinelayer.getFeatures()
        const mergeFeatures = [...lineFeatures,...lwpolylineFeatures,...polylineFeatures]
        const smallLayerSource = sLayer.getSource()
        for(let i = 0;i < mergeFeatures.length;i++) {
            smallLayerSource.addFeature(mergeFeatures[i])
        }
    }
}
